package timer;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * @author Created by chenxin34 on 2018/4/15 下午9:11.
 */
public class DelayQueuePressTest {
    private static long diff = 0;
    private static int count = 0;

    public static void main(String[] args) throws Exception {
        final DelayQueue<DelayedElement> delayQueue = new DelayQueue<DelayedElement>();
        count = 0;

        //生产者
        producer(delayQueue);

        //消费者
        consumer(delayQueue);

    }

    /**
     * 每秒钟 100个任务
     *
     * @param delayQueue
     */
    private static void producer(final DelayQueue<DelayedElement> delayQueue) {
        new Thread(() -> {
                for (int i = 0; i < 10000; i++){
                    DelayedElement element = new DelayedElement(1000, "task:" + i);
                    delayQueue.offer(element);
                    if (i % 100 == 0) {
                        try {
                            TimeUnit.MILLISECONDS.sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                System.out.println("producer done," + delayQueue.size());
            }).start();


    }

    /**
     * 消费者，从延迟队列中获得数据,进行处理
     *
     * @param delayQueue
     */
    private static void consumer(final DelayQueue<DelayedElement> delayQueue) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    DelayedElement element = null;

                    try {
                        element = delayQueue.poll(5, TimeUnit.SECONDS);
                        if (element == null){
                            break;
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    long current = System.currentTimeMillis();
                    System.out.println(element.msg + ",current=" + current + "，expire=" + element.expire);
                    diff += Math.abs(current - element.expire);
                    count++;
                }
                System.out.println("all=" + count);
                System.out.println(diff);
            }
        }).start();
    }


    static class DelayedElement implements Delayed {

        private final long delay; //延迟时间
        private final long expire;  //到期时间
        private final String msg;   //数据

        public DelayedElement(long delay, String msg) {
            this.delay = delay;
            this.msg = msg;
            expire = System.currentTimeMillis() + delay;    //到期时间 = 当前时间+延迟时间
        }

        /**
         * 需要实现的接口，获得延迟时间   用过期时间-当前时间
         *
         * @param unit
         * @return
         */
        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }

        /**
         * 用于延迟队列内部比较排序   当前时间的延迟时间 - 比较对象的延迟时间
         *
         * @param o
         * @return
         */
        @Override
        public int compareTo(Delayed o) {
            return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("DelayedElement{");
            sb.append("delay=").append(delay);
            sb.append(", expire=").append(expire);
            sb.append(", msg='").append(msg).append('\'');
            sb.append('}');
            return sb.toString();
        }
    }
}
